package graphicsExtended.animation.panelDrawer;

import graphicsExtended.animation.drawer.BackgroundDrawer;
import graphicsExtended.animation.drawer.StillFrameDrawer;
import graphicsExtended.animation.drawer.AnimationDrawer;
import graphicsExtended.animation.animationSequence.AnimationSequence;
import graphicsExtended.animation.animationSequence.StillFrame;
import graphicsExtended.animation.animationSequence.WrapperStillFrame;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.geom.AffineTransform;

/**
 *
 * @author Shimu
 * @date 9-Nov-2012
 */
public class AnimationPanelDrawer implements
        StillFrameDrawer, AnimationDrawer, BackgroundDrawer {

    private final Layer background;

    private final Layer stillFrames;

    private final Layer animationFrames;

    private int coordinateSpace = TOP_LEFT;

    private AffineTransform transform;

    public AnimationPanelDrawer(int width, int height) {
        this(width, height, TOP_LEFT);
    }

    /**
     * Instantiates an AnimationPanel with the given animator, width,
     * height, fps, cps, and coordinateSpace.
     * 
     * @param animator
     * @param width the width of the container panel
     * @param height the height of the container panel
     * @param fps the frames per second of the container, i.e. the number
     * of times the given animator's drawFrame method is called in a second.
     * @param cps the number of times the given animator's calculate method
     * is called in a second. 
     * @param coordinateSpace one of AnimationPanel.TOP_LEFT, or BOTTOM_LEFT.
     * If the given coordinateSpace is not one of the above, the default
     * coordinateSpace is used (TOP_LEFT).
     */
    public AnimationPanelDrawer(int width, int height, int coordinateSpace) {
        // Set an empty frame
        this.background = new Layer(width, height);
        this.stillFrames = new Layer(width, height);
        this.animationFrames = new Layer(width, height);

        //setCoordinateSpace(coordinateSpace);
    }

    /**
     * Sets the coordinateSpace of this AnimationPanel.
     * 
     * @param coordinateSpace one of AnimationPanel.TOP_LEFT, or BOTTOM_LEFT.
     * If the given coordinateSpace is not one of the above, the default
     * coordinateSpace is used (TOP_LEFT).
     */
    @Override
    public final void setCoordinateSpace(int coordinateSpace) {
        this.coordinateSpace = coordinateSpace;
        // Creates the identity transformation
        this.transform = new AffineTransform();

        if (coordinateSpace == TOP_LEFT) {
            // do nothing
        } else if (coordinateSpace == BOTTOM_LEFT) {
            //this.transform.translate(0, this.getHeight());
            this.transform.scale(1, -1);

        } else {
            // Invalid coordinate space, Do nothing, same as TOP_LEFT
        }

        /*
        SCREEN_GRAPHICS.translate(transform.getTranslateX(), transform.getTranslateY());
        SCREEN_GRAPHICS.scale(transform.getScaleX(), transform.getScaleY());
         * 
         */
    }

    public void paint(Graphics g) {
        stillFrames.drawAll();
        animationFrames.setImage(stillFrames.getImage());
        animationFrames.drawAll();

        //super.paintComponent(g);
        g.drawImage(animationFrames.getImage(), 0, 0, null);
        //super.paintBorder(g);
        //super.paintChildren(g);        
        //this.updateUI();
    }

    @Override
    public int getCoordinateSpace() {
        return this.coordinateSpace;
    }

    /**
     * Initialize the background, should only be called once at the beginning
     * @param frames 
     */
    @Override
    public void initBackground(Iterable<StillFrame> frames) {
        for (StillFrame frame : frames) {
            this.background.push(frame);
        }
        this.background.drawAll();
        this.stillFrames.setImage(this.background.getImage());
    }

    /**
     * Draw a still image.
     * @param stillFrame 
     */
    @Override
    public void draw(StillFrame stillFrame) {
        this.stillFrames.push(stillFrame);
    }

    /**
     * Erase a portion of the still images.
     * @param x
     * @param y
     * @param width
     * @param height 
     */
    @Override
    public void erase(int x, int y, int width, int height) {
        this.stillFrames.push(new WrapperStillFrame(
                this.background.getImage().getSubimage(x, y, width, height),
                new Point(x, y)));
    }

    @Override
    public void push(AnimationSequence animationSequence) {
        this.animationFrames.push(animationSequence);
    }
}